<?php
def("amicitia/arquitectura/","Accion");
def("amicitia/arquitectura/seguridad/excepciones/","RecursoSinPrivilegioException");

/**
 * Clase abstracta cuyas implementaciones deben determinar si un usuario
 * dado tiene acceso a un recurso específico.
 * 
 * @author Willy A. Kuster
 */
abstract class Guardian {
	
	private static $instancia;
	private $accion;
	private $consultores = array();
	
	private function __construct(Accion $accion){
		$this->accion = $accion;
	}
	
	private function getConsultor($mapeoConsultor) { 
		if(!array_key_exists($mapeoConsultor,$this->consultores)) {
			$claseConsultor = conf("seguridad","consultores",$mapeoConsultor,"clase");
			$rutaConsultor = conf("seguridad","consultores",$mapeoConsultor,"ruta");
			def($rutaConsultor,$claseConsultor);
			$this->consultores[$mapeoConsultor] = new $claseConsultor($this->accion);
		}
		return $this->consultores[$mapeoConsultor];
	}
	
	public function getNivel($mapeoConsultor) {
		$consultor = $this->getConsultor($mapeoConsultor);
		return $consultor->reportarNivel();
	}
	
	public static function getGuardian(Accion $accion = null){
		if (!isset(self::$instancia)) {
			$claseGuardian = conf("seguridad","guardian","clase");
			$rutaGuardian = conf("seguridad","guardian","ruta");
			def($rutaGuardian,$claseGuardian);
			self::$instancia = new $claseGuardian($accion);
		}
		return self::$instancia;
	}
	
	public function autorizar($recurso){
		if($this->setRecurso($recurso)){
			$nombreConsultor = $this->getTipoRecurso();
			$consultor = $this->getConsultor($nombreConsultor);
			
			$nivelActual = $consultor->reportarNivel();
			$nivelRecurso = $this->getNivelRecurso();
			if ($nivelActual<$nivelRecurso)
				$consultor->dispararExcepcion($_SERVER['REQUEST_URI'],$nombreConsultor,$nivelRecurso,$nivelActual);
		} else 
			throw new RecursoSinPrivilegioException($_SERVER['REQUEST_URI']);
	}
	
	abstract protected function setRecurso($recurso);
	abstract protected function getTipoRecurso();
	abstract protected function getNivelRecurso();
	
}
?>